package heven.holt.wan.android.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.paging.LoadState
import dagger.hilt.android.AndroidEntryPoint
import heven.holt.library.base.BaseFragment
import heven.holt.library.extensions.registerHeader
import heven.holt.library.loading.LoadingStateView
import heven.holt.library.loading.ViewType
import heven.holt.library.loading.delegate.ErrorViewDelegate
import heven.holt.library.loading.extensions.bindLoadingStateView
import heven.holt.library.paging.LoadStateFooterMoreAdapter
import heven.holt.wan.android.MainFragmentDirections
import heven.holt.wan.android.adapter.ArticleHomeAdapter
import heven.holt.wan.android.databinding.FragmentSystemArticleBinding
import heven.holt.wan.android.viewmodel.SystemArticleViewModel
import heven.holt.wan.android.viewmodel.factory.SystemArticleViewModelFactory
import heven.holt.wan.android.viewmodel.factory.SystemArticleViewModelProvider
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class SystemArticleFragment : BaseFragment<FragmentSystemArticleBinding>() {
    companion object {
        private const val SYSTEM_ARTICLE_CID = "cid"

        fun newInstance(cid: Int): SystemArticleFragment {
            val systemArticleFragment = SystemArticleFragment()
            systemArticleFragment.arguments = bundleOf(SYSTEM_ARTICLE_CID to cid)
            return systemArticleFragment
        }
    }

    private lateinit var loadingStateView: LoadingStateView

    @Inject
    lateinit var systemArticleViewModelProvider: SystemArticleViewModelProvider

    private val systemArticleViewModel: SystemArticleViewModel by viewModels {
        SystemArticleViewModelFactory(
            systemArticleViewModelProvider,
            arguments?.getInt(SYSTEM_ARTICLE_CID)!!
        )
    }

    private val articleHomeAdapter = ArticleHomeAdapter()

    override fun createDecorationView(): View {
        loadingStateView = binding.root.bindLoadingStateView()
        loadingStateView.register(ViewType.ERROR, ErrorViewDelegate {
            onReload()
        })
        loadingStateView.showLoadingView()
        return loadingStateView.decorView
    }

    override fun bindViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): FragmentSystemArticleBinding =
        FragmentSystemArticleBinding.inflate(inflater, container, false)

    override fun initView() {
        binding.springView.registerHeader {
            onReload()
        }

        val concatAdapter =
            articleHomeAdapter.withLoadStateFooter(LoadStateFooterMoreAdapter {
                articleHomeAdapter.retry()
            })

        articleHomeAdapter.addLoadStateListener {
            if (isDetached) return@addLoadStateListener
            when (it.refresh) {
                is LoadState.Loading -> {
                }
                is LoadState.NotLoading -> {
                    loadingStateView.showContentView()
                }
                is LoadState.Error -> {
                    loadingStateView.showErrorView()
                }
            }
        }

        articleHomeAdapter.setOnItemClickListener { view, articleModel ->
            val url = articleModel.link ?: return@setOnItemClickListener
            val direction = MainFragmentDirections.actionGlobalWebViewFragment(url)
            view.findNavController().navigate(direction)
        }

        binding.recyclerView.adapter = concatAdapter
    }

    override fun initData() {
        lifecycleScope.launch {
            systemArticleViewModel.flow.collectLatest {
                binding.springView.onFinishFreshAndLoad()
                articleHomeAdapter.submitData(it)
            }
        }
    }

    private fun onReload() {
        articleHomeAdapter.refresh()
    }
}